<!-- 文章内右侧目录 toc - docsify-plugin-toc -->
// <link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/docsify-plugin-toc@1.3.1/dist/light.css">
// <script src="https://gcore.jsdelivr.net/npm/docsify-plugin-toc@1.3.1/dist/docsify-plugin-toc.min.js"></script>
// toc: {
//     tocMaxLevel: 5,
//     target: 'h1, h2, h3, h4, h5',
//     ignoreHeaders:  ['<!-- {docsify-ignore} -->', '<!-- {docsify-ignore-all} -->']
// },

/**
 * 获取选择器信息
 *
 * @returns {string}
 */
function getSelectorString(){
    let tagNames = [];
    let target = window.$docsify.toc.target;
    if (target) {
        tagNames = target.split(",");
    }
    let scopeTagName = '#main';
    let scopeTag = window.$docsify.toc.scopeTag;
    if (scopeTag) {
        scopeTagName = scopeTag;
    }
    let selectorString = '';
    tagNames.forEach(function(tagName, index) {
        // 在第一个标签名之前不添加逗号
        if (index !== 0) {
            selectorString += ', ';
        }
        // 添加 #main 和当前标签名到选择器字符串
        selectorString += scopeTagName + ' ' + tagName.trim();
    });
    return selectorString ? selectorString : scopeTagName;
}

/**
 *
 * @param headings
 * @param path
 * @returns {string}
 */
function pageToC (headings, path) {
    let toc = ['<div class="page_toc">']
    const list = []
    const ignoreHeaders = window.$docsify.toc.ignoreHeaders || []
    // headings = document.querySelectorAll(`#main ${window.$docsify.toc.target}`)
    headings = document.querySelectorAll(this.getSelectorString());
    if (headings) {
        headings.forEach(function (heading) {
            const innerText = heading.innerText
            const innerHtml = heading.innerHTML

            let needSkip = false
            if (ignoreHeaders.length > 0) {
                needSkip = ignoreHeaders.some(str => {
                    return innerText.match(str);
                })
            }

            if (needSkip) return

            const item = generateToC(heading.tagName.replace(/h/gi, ''), innerHtml)
            if (item) {
                list.push(item)
            }
        })
    }
    if (list.length > 0) {
        toc = toc.concat(list)
        toc.push('</div>')
        return toc.join('')
    } else {
        return ''
    }
}

/**
 * To generate each ToC item
 *
 * @param level
 * @param html
 * @returns {string}
 */
function generateToC (level, html) {
    if (level >= 1 && level <= window.$docsify.toc.tocMaxLevel) {
        const heading = ['<div class="lv' + level + '">', html, '</div>'].join('')
        return heading
    }
    return ''
}

/**
 * scroll listener
 */
const scrollHandler = () => {
    const clientHeight = window.innerHeight
    // const titleBlocks = document.querySelectorAll(`#main ${window.$docsify.toc.target}`)
    const titleBlocks = document.querySelectorAll(this.getSelectorString());
    let insightBlocks = []
    titleBlocks.forEach((titleBlock, index) => {
        const rect = titleBlock.getBoundingClientRect()
        // still in sight
        if (rect.top <= clientHeight && rect.height + rect.top > 0) {
            insightBlocks.push(index)
        }
    })
    const scrollingElement = document.scrollingElement || document.body
    // scroll to top, choose the first one
    if (scrollingElement.scrollTop === 0) {
        insightBlocks = [0]
    } else if (scrollingElement.offsetHeight - window.innerHeight - scrollingElement.scrollTop < 5 &&
        insightBlocks.length > 0) {
        // scroll to bottom and still multi title in sight, choose the first one
        insightBlocks = [insightBlocks[0]]
    }
    if (insightBlocks.length) {
        const tocList = document.querySelectorAll('.page_toc>div')
        tocList.forEach((t, index) => {
            if (index === insightBlocks[0]) {
                t.classList.add('active')
            } else {
                t.classList.remove('active')
            }
        })
    }
}

/**
 * 载入插件
 *
 * @type {*[]}
 */
window.$docsify.plugins = [].concat(function(hook, vm) {

    hook.doneEach(function () {
        const nav = window.Docsify.dom.find('.toc-nav')
        if (nav) {
            nav.innerHTML = pageToC().trim()
            if (nav.innerHTML === '') {
                window.Docsify.dom.toggleClass(nav, 'add', 'nothing')
                window.document.removeEventListener('scroll', scrollHandler)
            } else {
                window.Docsify.dom.toggleClass(nav, 'remove', 'nothing')
                scrollHandler()
                window.document.addEventListener('scroll', scrollHandler)
            }
        }
    })

    hook.mounted(function () {
        const content = window.Docsify.dom.find('.content')
        if (content) {
            const nav = window.Docsify.dom.create('aside', '')
            window.Docsify.dom.toggleClass(nav, 'add', 'toc-nav')
            window.Docsify.dom.before(content, nav)
        }
    })

}, window.$docsify.plugins);